package icasue.base.utils.script;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.Charset;

/**
 * @Author: Qiao Hang
 * @CreateDate: 2021/2/20 上午11:13
 * @UpdateDate:
 * @Description:
 */
public class SOKserver {

    public static void main(String[] args) {
        //创建SocketServer 指定Socket交互端口4477.
        ServerSocket server = null;
        try {
            server = new ServerSocket(4477);
        }catch (IOException e){
            e.printStackTrace();
        }
        //创建单一的Socket连接通道，并阻塞到该Socket连接被客户端请求数据交换
        Socket socket = null;
        try {
            socket = server.accept();
        }catch (IOException e){
            e.printStackTrace();
        }
        try {
            //确认Socket被创建，且未关闭，处于交互的Ready状态,
            if(socket != null){
                //服务端应答内容, 客户端发送的数据内容
                String serverAns = null;
                String clientQue = null;
                //Socket客户端Identity信息
                String hostAddress = socket.getInetAddress().getHostAddress();
                String hostName = socket.getInetAddress().getHostName();
                //来组客户端的数据输入读取流
                BufferedReader clientReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                //构建目标为客户端的数据输除流
                PrintWriter clientWriter = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
                //构建目标为服务端的应答数据读取流
                BufferedReader serverAnsReader = new BufferedReader(new InputStreamReader(System.in, Charset.forName("utf-8")));
                //死循环处理服务端和客户端的Socket交互
                while (socket != null && socket.isConnected()){
                    //以线程阻塞的方式等待来组客户端的数据输入，并针对数据输入完成服务端的业务处理
                    clientQue = clientReader.readLine();
                    if(clientQue.equalsIgnoreCase("BYE")){ break; }

                    /*省略服务端的业务处理流程.....*/
                    System.out.println(String.format("%s  %s  :: %s",hostName,hostAddress,clientQue));

                    //服务端针对本次客户端的交互业务执行应答,这里以控制台输入的方式模拟服务端应答, 以线程阻塞的方式
                    serverAns = serverAnsReader.readLine();

                    //将服务端的应答以数据流的形式写回本次客户端开启的Socket的输出流中，数据将流到客户端的开启的Socket的输入流中获取.
                    clientWriter.println(serverAns);
                    clientWriter.flush();

                    //服务端应答为BYE时，也需要给出明确的应答后结束，否则客户端一直在阻塞等待服务端的应答readLine.
                    if(serverAns.equalsIgnoreCase("BYE")){ break; }
                }
                if(clientWriter != null){clientWriter.close();}
                if(clientReader != null){clientReader.close();}
                if(socket != null){ socket.close(); }
                if(server != null){ server.close(); }
            }
        }catch (Throwable e){
            e.printStackTrace();
        }
    }
}
